/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controllers;

import Controllers.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entities.Person;
import Entities.Pet;
import Entities.Record;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author Heinz Hernandez
 */
public class PetJpaController implements Serializable {

    public PetJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Pet pet) {
        if (pet.getRecordList() == null) {
            pet.setRecordList(new ArrayList<Record>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Person perIdown = pet.getPerIdown();
            if (perIdown != null) {
                perIdown = em.getReference(perIdown.getClass(), perIdown.getPerId());
                pet.setPerIdown(perIdown);
            }
            Person perId = pet.getPerId();
            if (perId != null) {
                perId = em.getReference(perId.getClass(), perId.getPerId());
                pet.setPerId(perId);
            }
            List<Record> attachedRecordList = new ArrayList<Record>();
            for (Record recordListRecordToAttach : pet.getRecordList()) {
                recordListRecordToAttach = em.getReference(recordListRecordToAttach.getClass(), recordListRecordToAttach.getRecId());
                attachedRecordList.add(recordListRecordToAttach);
            }
            pet.setRecordList(attachedRecordList);
            em.persist(pet);
            if (perIdown != null) {
                perIdown.getPetList().add(pet);
                perIdown = em.merge(perIdown);
            }
            if (perId != null) {
                perId.getPetList().add(pet);
                perId = em.merge(perId);
            }
            for (Record recordListRecord : pet.getRecordList()) {
                Pet oldPetIdOfRecordListRecord = recordListRecord.getPetId();
                recordListRecord.setPetId(pet);
                recordListRecord = em.merge(recordListRecord);
                if (oldPetIdOfRecordListRecord != null) {
                    oldPetIdOfRecordListRecord.getRecordList().remove(recordListRecord);
                    oldPetIdOfRecordListRecord = em.merge(oldPetIdOfRecordListRecord);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Pet pet) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Pet persistentPet = em.find(Pet.class, pet.getPetId());
            Person perIdownOld = persistentPet.getPerIdown();
            Person perIdownNew = pet.getPerIdown();
            Person perIdOld = persistentPet.getPerId();
            Person perIdNew = pet.getPerId();
            List<Record> recordListOld = persistentPet.getRecordList();
            List<Record> recordListNew = pet.getRecordList();
            if (perIdownNew != null) {
                perIdownNew = em.getReference(perIdownNew.getClass(), perIdownNew.getPerId());
                pet.setPerIdown(perIdownNew);
            }
            if (perIdNew != null) {
                perIdNew = em.getReference(perIdNew.getClass(), perIdNew.getPerId());
                pet.setPerId(perIdNew);
            }
            List<Record> attachedRecordListNew = new ArrayList<Record>();
            for (Record recordListNewRecordToAttach : recordListNew) {
                recordListNewRecordToAttach = em.getReference(recordListNewRecordToAttach.getClass(), recordListNewRecordToAttach.getRecId());
                attachedRecordListNew.add(recordListNewRecordToAttach);
            }
            recordListNew = attachedRecordListNew;
            pet.setRecordList(recordListNew);
            pet = em.merge(pet);
            if (perIdownOld != null && !perIdownOld.equals(perIdownNew)) {
                perIdownOld.getPetList().remove(pet);
                perIdownOld = em.merge(perIdownOld);
            }
            if (perIdownNew != null && !perIdownNew.equals(perIdownOld)) {
                perIdownNew.getPetList().add(pet);
                perIdownNew = em.merge(perIdownNew);
            }
            if (perIdOld != null && !perIdOld.equals(perIdNew)) {
                perIdOld.getPetList().remove(pet);
                perIdOld = em.merge(perIdOld);
            }
            if (perIdNew != null && !perIdNew.equals(perIdOld)) {
                perIdNew.getPetList().add(pet);
                perIdNew = em.merge(perIdNew);
            }
            for (Record recordListOldRecord : recordListOld) {
                if (!recordListNew.contains(recordListOldRecord)) {
                    recordListOldRecord.setPetId(null);
                    recordListOldRecord = em.merge(recordListOldRecord);
                }
            }
            for (Record recordListNewRecord : recordListNew) {
                if (!recordListOld.contains(recordListNewRecord)) {
                    Pet oldPetIdOfRecordListNewRecord = recordListNewRecord.getPetId();
                    recordListNewRecord.setPetId(pet);
                    recordListNewRecord = em.merge(recordListNewRecord);
                    if (oldPetIdOfRecordListNewRecord != null && !oldPetIdOfRecordListNewRecord.equals(pet)) {
                        oldPetIdOfRecordListNewRecord.getRecordList().remove(recordListNewRecord);
                        oldPetIdOfRecordListNewRecord = em.merge(oldPetIdOfRecordListNewRecord);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = pet.getPetId();
                if (findPet(id) == null) {
                    throw new NonexistentEntityException("The pet with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Pet pet;
            try {
                pet = em.getReference(Pet.class, id);
                pet.getPetId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The pet with id " + id + " no longer exists.", enfe);
            }
            Person perIdown = pet.getPerIdown();
            if (perIdown != null) {
                perIdown.getPetList().remove(pet);
                perIdown = em.merge(perIdown);
            }
            Person perId = pet.getPerId();
            if (perId != null) {
                perId.getPetList().remove(pet);
                perId = em.merge(perId);
            }
            List<Record> recordList = pet.getRecordList();
            for (Record recordListRecord : recordList) {
                recordListRecord.setPetId(null);
                recordListRecord = em.merge(recordListRecord);
            }
            em.remove(pet);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Pet> findPetEntities() {
        return findPetEntities(true, -1, -1);
    }

    public List<Pet> findPetEntities(int maxResults, int firstResult) {
        return findPetEntities(false, maxResults, firstResult);
    }

    private List<Pet> findPetEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Pet.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Pet findPet(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Pet.class, id);
        } finally {
            em.close();
        }
    }

    public int getPetCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Pet> rt = cq.from(Pet.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
